package com.sky.service.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.ReportMapper;
import com.sky.service.ReportService;
import com.sky.vo.OrderReportVO;
import com.sky.vo.SalesTop10ReportVO;
import com.sky.vo.TurnoverReportVO;
import com.sky.vo.UserReportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private OrderMapper orderMapper;

    /**
     * 统计营业额
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {
        // 声明一个列表用于存放日期数据  等会直接吧列表转化为字符串
        List<LocalDate> dateList = getDateList(begin, end);

        //统计营业额
        List<Double> turnoverList = new ArrayList<>();
        for (LocalDate date : dateList) {
            // 查询出数据库每天的营业额 然后计算 营业额
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            Double result = reportMapper.getSum(beginTime, endTime);
            //处理营业额为null时的异常
            result = result == null ? 0.0 : result;
            turnoverList.add(result);
        }

        //封装数据
        return TurnoverReportVO
                .builder()
                .dateList(StringUtils.join(dateList, ","))
                .turnoverList(StringUtils.join(turnoverList, ","))
                .build();
    }

    /**
     * 统计用户数据
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
        //统计总用户量配置
        Integer totalUser = reportMapper.getTotalUser();
        //日期列表的配置
        List<LocalDate> dateList = getDateList(begin, end);

        //统计每日新增用户量
        List<Double> newUserTotal = new ArrayList<>();
        for (LocalDate date : dateList) {
            // 获取指定日期的00:00:00
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            // 获取指定日期的23:59:59
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            Integer result = reportMapper.getNewUser(beginTime, endTime);
            //处理营业额为null时的异常
            result = result == null ? 0 : result;
            newUserTotal.add(Double.valueOf(result));
        }


        //构造返回数据
        return UserReportVO
                .builder()
                .dateList(StringUtils.join(dateList, ","))
                .totalUserList(String.valueOf(totalUser))
                .newUserList(StringUtils.join(newUserTotal, ","))
                .build();
    }

    /**
     * 统计订单数据
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO getOrdersStatistics(LocalDate begin, LocalDate end) {
        //获取两个日期中间所有的日志集合
        List<LocalDate> dateList = getDateList(begin, end);
        //获取订单总数
        Integer totalOrderCount = reportMapper.getTotalOrderCount();
        //获取有效订单总数
        Integer validTotalOrderCount = reportMapper.getValidTotalOrderCount();

        //统计每天的订单数列表
        List<Double> orderCountList = new ArrayList<>();
        //统计每天的有效订单数列表
        List<Double> validOrderCountList = new ArrayList<>();
        for (LocalDate date : dateList) {
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            //统计每天的订单数
            Integer orderCount = reportMapper.getOrderCount(beginTime, endTime);
            orderCount = orderCount == null ? 0 : orderCount;
            orderCountList.add(Double.valueOf(orderCount));

            //统计每天的有效订单数
            Integer validOrderCount = reportMapper.getValidOrderCount(beginTime, endTime);
            validOrderCount = validOrderCount == null ? 0 : validOrderCount;
            validOrderCountList.add(Double.valueOf(validOrderCount));
        }


        return OrderReportVO
                .builder()
                .dateList(StringUtils.join(dateList, ","))
                .orderCompletionRate(Double.valueOf(validTotalOrderCount) / Double.valueOf(totalOrderCount))
                .orderCountList(StringUtils.join(orderCountList, ","))
                .validOrderCountList(StringUtils.join(validOrderCountList, ","))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validTotalOrderCount)
                .build();
    }

    /**
     * 统计销量top10的数据
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO getTop10(LocalDate begin, LocalDate end) {
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        List<GoodsSalesDTO> goodsSalesDTOList = orderMapper.getSalesTop10(beginTime, endTime);
        log.info("goodsSalesDTOList:{}", goodsSalesDTOList);

        String nameList = StringUtils.join(goodsSalesDTOList.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList()), ",");
        String numberList = StringUtils.join(goodsSalesDTOList.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList()), ",");
        log.info("nameList:{}", nameList + "numberlist:" + numberList);

        return SalesTop10ReportVO.builder()
                .nameList(nameList)
                .numberList(numberList)
                .build();
    }


    /**
     * 该方法的作用就是传入两个日期文件 然后他会自动给你把中间的日志给转化为一个datalist列表
     *
     * @param begin
     * @param end
     * @return
     */

    public List<LocalDate> getDateList(LocalDate begin, LocalDate end) {
        // 声明一个列表用于存放日期数据  等会直接吧列表转化为字符串
        List<LocalDate> datelist = new ArrayList<>();

        datelist.add(begin);
        while (!begin.isBefore(end)) {
            begin = begin.plusDays(1);
            datelist.add(begin);
        }
        return datelist;
    }
}
